Log In  
BBS > Lexaloffle Community Superblog
This is a combined feed of all Lexaloffle user blogs. For Lexaloffle-related news, see @zep's blog.

All | Following | PICO-8 | Voxatron | General | Off-site
[ :: Read More :: ]

Hi,

I'm pulling together a simple animation that shows some electrochemical concepts.
I've managed to get an "ion" moving around a simple electrochemical cell (anticlockwise flow) using some random movements with some bias to help "push" the ion in the right direction to simulate flow. Its not perfect and there are no doubt much simpler ways to do this, but my coding skills aren't up to it so I've hacked this together - please excuse the mess!

Anyway, I am trying to get the white "ion" to turn green when it hits the electrode (aka grey box) and stay green. I'm doing this by checking if the "ion" is within the bounds of the electrode, and also that the electrode is powered up (variable pwr=1). As far as I can see, it should work, but after literally hours trying to figure out why its not working, I'm close to giving up, and thought I'd see if I was missing a really obvious thing - as I say, I'm not a good coder, just muddle by!

Any help would be very much appreciated.

All the best,
Paul.

PS: another problem that I've not fixed is the switching on/off of the power to the electrode. Should be done using a simple btn press, but for some reason this isn't working either. Again, any suggestions much appreciated. Thanks :-)

Cart #gunukuzibu-0 | 2020-11-14 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
1

P#84232 2020-11-14 15:33 ( Edited 2020-11-14 23:37)
[ :: Read More :: ]

This is a simple agar.io like game that I made

by snoo8
Cart #agar-0 | 2020-11-14 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
2

How to play:
Arrow keys to move
X to reset

Eat circles that are smaller than you by moving to them. The more you eat, the larger you get and the more circles you can eat. Be careful though, as you might get eaten by larger circles! You might get eaten as soon as you eat another circle because I made it so that a circle spawns (that might be smaller or larger than you) as soon as you eat a circle.

P#84223 2020-11-14 10:00
[ :: Read More :: ]

To commemorate the ending of an era that only this generation enjoyed, I decided to re-skin a demo of an already existing game, because yes.

LABEL CORRUPT, DON'T MIND IT JUST PLAY THE DAMN GAME

Cart #mark_and_ethan-0 | 2020-11-13 | Code ▽ | Embed ▽ | No License

P#84210 2020-11-13 23:34
[ :: Read More :: ]

@zep:

I teach a LOT of students PICO-8 and lately I've been mostly teaching online classes over Zoom. I'm usually doing this webinar style where I am the presenter and the students are participants. I can't see their screen, but they can see mine and there's a Q&A chat window where they can ask questions and so forth.

It would be extremely helpful to be able to copy console error messages to the clipboard. Currently you can hit CTRL-C in the console to copy what's typed into the command prompt, but it would be even more useful, if the prompt was empty, to use CTRL-C to copy the last error generated. Like this:

This would make it so much easier to help students when they run into errors, especially the very young students. If they get an error, they can just hit CTRL-C and paste the error into the Zoom chat. This would also be helpful for people trying to get other live help online, such as from Discord.

P#84208 2020-11-13 23:11 ( Edited 2020-11-13 23:12)
[ :: Read More :: ]

Hi,

I am working on a small cart to demonstrate an engineering process for a colleague who wants to spice up a PowerPoint presentation he is giving.

Does anyone know if its possible to embed a Cart (in HTML format??) into a PowerPoint presentation so that he can run it from within his presentation?

Any help much appreciated.

All the best,
Paul :-)

PS: Am asking here since I can't test this as I use a Mac and don't have PowerPoint! Thanks :-)

P#84204 2020-11-13 21:09 ( Edited 2020-11-13 22:24)
[ :: Read More :: ]

i've been tinkering around with Buildroot and got me an image that I'm happy with that boots up, connects to wifi then starts pico-8. the problem I'm having is that once pico-8 starts, the inputs aren't recognized as if pico-8 doesn't have focus. I'm not sure how to force it to have focus though. anyone have any idea what might be causing the issue? i haven't tried using a controller, so I have no idea if that would work or not. my goal was a minimal image for running Pico-8 :)

it does the same thing, even if I run pico-8 manually and not @ startup.
here is the output of me using the keyboard while pico-8 is up and running and after I have killed pico8_dyn from the console, so I know the OS is recognizing inputs, just not pico-8.

thanks in advance for any advice!

P#84201 2020-11-13 19:35 ( Edited 2020-11-14 06:32)
[ :: Read More :: ]

So, I tried everything, then I created a profile to ask this: is there any way to play with the D-pad of a game controller on the embedded PICO-8 player?

Currently, the D-pad is very weirdly mapped to the menu, so I can't even set my gamepad with JoyToKey. There is no way to change this weird mapping, and there is no way to disable joystick detection. I don't understand this choice at all, is there any way to escape it?

P#84200 2020-11-13 18:39
[ :: Read More :: ]

Cart #nayadunaze-1 | 2020-11-13 | Code ▽ | Embed ▽ | No License
4


Nine tweettweetjam5 entries in one cartridge!

  • VULF 3D
    • Explore a maze a first person raycast game!
  • There be Treasure!
    • Use triangulation to find the treasure!
  • PADAR
    • Defend yourself from incoming bogeys!
  • Big Donut
    • Become the donut magnate in this idle clicker!
  • Diskette
    • Dodge the disks, get that high score, don't bleed out on the floor!
  • Go
    • 2500+ year old board game in 560 chars!
  • Blitzar
    • Sixteen hundred stars to explore in this space sim!
  • Dither Wars
    • Color wars strategy game using mode7!
  • Pay-Co Model 560
    • Crack the virtually uncrackable in this rhythm lockpicking game!

CTRL-R to return to menu.

P#84157 2020-11-13 17:59
[ :: Read More :: ]

Cart #battleshipv1-1 | 2020-11-13 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
3

This is my first 99% finished game, been a project for about 3 years that I only recently got to a fully playable state. The code is indicative of my programming skills changing over time. Any feedback or bug reports would be welcomed!

P#84192 2020-11-13 14:55 ( Edited 2020-11-13 18:22)
[ :: Read More :: ]
P#84190 2020-11-13 13:54
[ :: Read More :: ]

Cart #fishbone-0 | 2020-11-12 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
15

First game using Pico-8! So happy I could finish a game by myself and actually post it.
Anyway, hope you enjoy despite of being super simple and of course let me know if you have any suggestions for the future :)

P#84171 2020-11-12 21:53
[ :: Read More :: ]

Can you put mice into Jelpi?

So, I've been messing around with mice and the pico-8. Now earlier I was playing Jelpi and thought "Hmm, I Wonder if I can put touchscreen on this?" Now I Myself don't have a touchscreen! But for people who do not, CAN YOU LET THEM PLAY WITH NO CONTROLLER? I'm gonna try, but anyone of you can leave the cart here if you make it.

link to a mouse cart https://www.lexaloffle.com/bbs/cposts/2/22286.p8.png

EDIT: Old post, I didn't want to delete it. Sorry for all the caps and stuff.

P#84168 2020-11-12 20:05 ( Edited 2022-10-01 19:19)
[ :: Read More :: ]

Cart #d8ing-0 | 2020-11-12 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
3

since i've been a little obsessed with death stranding recently, i decided to make a little demake for the tweet tweet jam. i'm quite happy with how it turned out and how much functionality i managed to squeeze in. it even has the scanner haha
arrows + x

it's on itch.io as well

P#84163 2020-11-12 18:31 ( Edited 2020-11-12 18:35)
[ :: Read More :: ]

Cart #spaceinvader0-8 | 2020-11-15 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
1


INSTRUCTIONS

X = fire main weapon. This can destroy both invaders and their bombs and mothership.

Z = fire particle beam, which takes time to charge up in top-left. This is ultra destructive but can only destroy invaders; not their bombs or mothership.

Arrow left or right to control ship

Invaders that dive-bomb are worth more.

A mothership will occasionally appear and respawn invaders. Shooting it down is worth max points.
When the mothership spawns new invaders, they take a few seconds to materialize; shooting them in that state is worth more.

As you progress through the levels, the mayhem increases and gets faster.

Of programming note: the Animations and Sprt functions implement a general-purpose system for animating sprites in a declarative way. Just specify the state transition in a table and call the Animation function with the object to animate, and it will automatically transition the object through the specified states, including looping and chaining.

P#84155 2020-11-12 15:22 ( Edited 2023-01-14 06:43)
[ :: Read More :: ]

Cart #peachbross-0 | 2020-11-12 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#84149 2020-11-12 10:57
[ :: Read More :: ]

Cart #misizefide-0 | 2020-11-12 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

THIS CART USES THE DEVKIT MOUSE!!!!
This is just a fun little example :D

P#84139 2020-11-12 03:38
[ :: Read More :: ]

oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooi

P#84128 2020-11-11 20:08
[ :: Read More :: ]
P#84124 2020-11-11 19:50
[ :: Read More :: ]

People have been asking how I managed to fit a multiplayer game into the space of two tweets (560 chars) for TweetTweetJam5, so I thought I'd write a mini tutorial to explain the process!

We'll cover:

  • Stuff you need (such as javascript libraries, and where to get them)
  • How pico-8 talks to the outside world (General Purpose Input Output - GPIO - memory)
  • How to have a conversation between pico-8, the web browser running a pico-8 cart, and a database server
  • How to implement multiplayer that allows users to play against 'replays' or 'ghosts' of previous players (which is rather cool and under-explored territory imo)

We won't cover:

  • Server-side coding such as would be required for concurrent multiplayer gaming like, er, Counterstrike or something (do people still play Counterstrike?)
  • Setting up a specific online database to hold your replay data - I use FatFractal http://fatfractal.com, but I am sure there are loads of options these days. Anything that can be accessed from client-side Javascript will do just fine.
  • How to make games or code pico-8 - this is an advanced-level tutorial I'd say

So let's dive in ...

A quick example or two

I've used the method for a few pico-8(**) games now - if you want to get a feel for what this tutorial will teach you, feel free to play these (and please let me know what you think!) - I'll wait...

Things we need

GPIO: How pico-8 talks to the outside world

GPIO (general purpose input output) is a 128 byte segment of pico-8 memory, starting at 0x5f80. We can access it like any other chunk of pico-8 RAM, using peek, poke, memcpy and memset. Each of the 128 GPIO bytes can store a number in the range 0--0xff (0--255 in decimal). If we want to store larger numbers we can do so using poke2 (0--0xffff) or, for full precision, poke4 (0--0xffff.ffff). For TweetCarts we can make use of handy function aliases @=peek, %=peek2, $=peek4.

GPIO memory is shared between the pico-8 cart, and the host environment (in our case, this is the HTML page running the exported cart Javascript). This means that both sides can read from, and write to, the memory. This allows data to be passed back and forth 128 bytes at a time between pico-8 and the outside world. We need two tricks. The first trick is to set up the 'conversation' so that both sides don't try to 'speak' at the same time (which would result in lost data). The second trick is to encode the game data so it can pass through the small 128 byte buffer. Let's take the second one first.

Passing game data in 128 byte buffer

How to approach this really depends on your specific game. For my games, I want to save the player position as a ghost replay. It is convenient to fit a replay into a single 128-byte chunk, so that the whole thing can be sent to the server in one transaction. Splitting across multiple chunks requires more sophisticated synchronisation and is beyond the scope of this article, but there are other resources on lexaloffle.com that might give some ideas here.

Now, 128 bytes is not much space. If we are storing x,y coordinates at full pico-8 numerical precision, each 'frame' would require 8 bytes meaning we could only store 16 frames, which would cover 1/4 of a second's worth of action at 60fps - not much of a replay! We therefore need to intelligently compress information.

The first compression is to use lower precision numbers, just in the range 0-255, so that each frame can be stored in two bytes. This gives per-pixel accuracy for games where the world doesn't scroll. For scrolling games we can divide by 2, or 4 etc to get per 2-pixel or per-4-pixel accuracy but with the ability to represent numbers out to 512 or 1024, to support bigger game worlds.

The second compression is to only record replay frames every N pico-8 frames, using something like if(t%10==0)add(replay,{x,y}). This snippet appends a replay frame every 10 pico-8 frames.

But won't these compression methods lead to replay sprites jumping around the screen in an unappealing way? Yes! But to get around that we can interpolate between two frames when rendering replays, to smoothly blend replay spite positions from one replay frame to the next.

Oh, and one more thing, we can't use all 128 bytes of GPIO for replay frames - we need at least one byte to manage the "conversation" (more on that next), and perhaps more bytes to hold things like the current level number, the player's name, the score, and the number of replay frames in the packet (if this isn't constant between plays).

Here is a gif from Infinite Zombies with Friends. The player moves over extended ranges, and can take up to a minute. By using interpolation the replayed motion is nice and smooth, even though the replays use hardly any data. (apologies for the poor colour reproduction here - blame GiphyCapture)

Managing the 'conversation' between pico-8 and the host environment

The 'conversation' between the cart, the browser, and the cloud database (the 'communications protocol' if you want the proper term) uses the first byte of the GPIO array to control which party is 'speaking' at any given time. If the cart is sending data to the browser, it memcpy's the data into the GPIO memory, and sets the first byte (let's call it the comms byte) to 1 with poke(0x5f80,1). The browser listens for changes to the GPIO buffer, and if it sees a comms byte of 1, sends the replay data off to the cloud database.

On the other hand, if the browser wants to send data to the cart, it loads the data for a single replay into GPIO and set the comms byte to 2. The cart checks the state of the comms byte once per frame, and if it sees a 2, knows it can load 128 bytes from GPIO to user data, with memcpy(0x4300 + 128*N, 0x5f80, 128) where N is the number of replays it has already loaded. The cart then sets the comms byte to 3, which is the cart's way of signalling the browser that it is ready for more data.

The final matter to resolve is 'who speaks first'. I always have the cart speak first, by setting special comms state to 9. The simple reason being that the browser side is ready before the cart, and may have data ready to send before the cart is ready to receive. By starting with the cart, the conversation can be driven more directly by the needs of the player. For instance, maybe the cart needs data for a specific map - in this case the browser needs the cart to tell it which map that is, before data can be fetched from the cloud.

If this is all rather abstract, hopefully the index.html excerpt below will help things make a bit more sense:

<script src="pico8-gpio-listener.js"></script>

<!-- REPLACE THIS WITH YOUR OWN DATABASE JS API!! -->
<script src="FatFractal.js"></script> 

<script type="text/javascript">

// This array is how we read/write GPIO on the browser side
var pico8_gpio = new Array(128);

// benwiley4000's GPIO library - "other GPIO libraries are also available"
var gpio = getP8Gpio();

// register a callback handler which is triggered whenever the GPIO is 
// changed by EITHER pico-8 or the browser
gpio.subscribe(function(indices) {

      // read current communication state - who is 'speaking'? Cart, or browser?
      var comms_state = gpio[0];

      // these comms states are set by the browser side, and so we don't want 
      // to respond to them (no 'talking to ourself')
      if (comms_state==4) return;
      if (comms_state==0) return;
      if (comms_state==2) return;

      if (comms_state==9)
      {
            // this represents the cart saying 'hello', and triggers us to fetch data 
            // from our cloud database
            loaded_replays = // YOUR DATABASE QUERY HERE
            nrep = loaded_replays.length;

            if (nrep>0)
            {
                        // lock GPIO - this means that as we insert data into the GPIO 
                        // array, we won't keep triggering the browser 
                        // ('no talking to ourself')
                        gpio[0]=4;

                        // pack replay data into GPIO array
                        for(var i = 1; i < 128; i++)
                        {
                                    gpio[i]=loaded_replays[nrep-1].raw_gpio_n[i];

                        }

                        // decrement counter so we can keep track of what's already sent
                        nrep-=1;

                        // Setting the GPIO comms byte to 2 indicates to the cart that 
                        // there is data ready for them to consume
                        gpio[0]=2;
            }
            else
            {
                        // If there is no data to send, we indicate this to the cart by 
                        // setting the GPIO comms byte to 0
                        gpio[0]=0;
            }
      }

      else if (comms_state==1)
      {
            // This comms state represents the cart SENDING data to the browser. All we 
            // have to do here is push it up to the cloud server.
            // We pack the whole GPIO array into a field called raw_gpio, and send it to 
            // our cloud database service (not shown)
            var raw_gpio = new Array(128);
            for(var i = 0; i < 128; i++)
            {
                  raw_gpio[i]=gpio[i];
            }

            // SEND raw_gpio TO YOUR CLOUD DATABASE

            // No need to do anything else with GPIO 
      }

      else if (comms_state==3)
      {
        // In this comms state, the cart is signalling that they have received a data 
        // item, and are ready for more if there is more to send.
        // We either send more (and set comms state back to 2) or if there is nothing
        // to send, set comms state to 0

        if(nrep>0)
        {
            // Lock to avoid 'talking to ourself'
            gpio[0]=4;

            // pack replay into GPIO memory
            for(var i = 1; i < 128; i++)
            {
                    gpio[i]=loaded_replays[nrep-1].raw_gpio_n[i];
            }

            // decrement counter
            nrep-=1;

            // signal cart that the data is ready for them to read from GPIO
            gpio[0]=2;
        }
        else
        {
            // no more data - indicate by setting gpio comms state to 0
            gpio[0]=0;
        }
      }

},
true); // don't forget that 'true'!

Here's a tip: you won't need to export the .html file every time. You can do EXPORT FOO.JS to just export the javascript innards. I append a version number here, and then update the FOO_v?.js reference in index.html. Bonus tip, for your game to work on itch.io, the html file must be called index.html.

Summary

If you've read this far, you already know that Pico-8 is a wonderfully expressive tool. I hope this article has given you some ideas for how you could extend your exploration of Pico-8's creative possibilities. I would be very grateful for any comments, feedback, or questions - I always reply promptly :) Looking forward to seeing what you create with Pico-8 GPIO online functionality!

Complete source code for Massive Multiplayer Moon Lander

The code is fully 'golfed' to fit in minimal size- 560 characters in this case - in no way would I recommend writing code in this style unless it is absolutely necessary!

Unpacking all of this is beyond the scope of this article, but there are loads of great tweetcart resources on lexaloffle.com and elsewhere.

g=0x5f80m=memcpy
u=0x4300s=memset
k=63s(g,9,1)n=1p=poke::❎::d=print
o=128t=0r=1x=o*rnd()y=0q=0v=0z=0.05f=99w=0::_::cls()circfill(k,230,o,6)rect(0,0,1,f,9)
?"❎",32,105,8
if(@g==2)m(u+n*o,g,o)p(g,3)n+=1
b=0a=0j=btn
if(f>0)then
if(j(⬅️))a+=z b-=z d("ˇ",x-3,y+4,9)f-=1
if(j(➡️))a-=z b-=z d("ˇ",x+4,y+4,9)f-=1
end
q+=a
v+=b+z
if pget(x+3,y+5)==8and v<1then
w=1else
x+=q 
y+=v
end
for e=1,n-1do
h=@(u+e*o+r*2)l=@(u+e*o+r*2+1)
if(r>k)h=o
?"웃",h,l,2
end
?"웃",x,y,7
flip()t+=1if(t%3==0and r<k)p(u+r*2,x)p(u+r*2+1,y)r+=1
if(y<o*2and w<1)goto _
p(u,1)m(g,u,o)
if(w<1)goto ❎

Thanks for reading!

Superfluid
@superfluid
itch.io: https://superfluid.itch.io
twitter: @trappyquotes

(**)
And fwiw a couple of iOS games too:

P#84109 2020-11-11 16:00 ( Edited 2020-11-12 10:08)
[ :: Read More :: ]

Cart #navia-0 | 2020-11-11 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
2


I,m Navia.
I test your navigation skills.
Please navigate me with three looping locators.

P#84113 2020-11-11 14:10
View Older Posts